"""照片标准化

处理照片标准化
"""

import math
import os
import string
from enum import StrEnum

from typing import Any, List, Union, Tuple

from PIL import Image, ImageColor, ImageDraw, ImageFont
from PIL.ImageChops import offset

from .index import base642PIL, PIL2base64, hex_to_rgb

from ..model import BaseModel
from ..model.basics_model import Rectangle
from ..model.photo_standard_model import (
    PhotoStandardConfig,
    PhotoStandardMode,
    PhotoStandardWarning,
)
from ..model.baidu import EyeStatus
from ..resource import resource_dir
from ..exception import BaseException


class ErrorCode(StrEnum):
    # 脸长 < 0.53 脸宽大于》0.62
    FACE_MINIMUM_WIDTH = "E000"
    FACE_WIDTH_LARGER = "E001"
    FACE_WIDTH_SMALL = "E002"
    BODY_SMALL = "E003"
    BODY_LARGER = "E004"
    STANARD_WIDTH_LARGER = "E005"
    STANARD_HEIGHT_LARGER = "E006"
    BOTTOM_HANGING = "E007"
    LEFT_HANGING = "E008"
    RIGHT_HANGING = "E009"
    FACE_ROTATION = "E010"
    FACE_MASK = "E011"
    FACE_BLUR = "E012"
    HEAD_TOP = "E013"

    def __str__(self):
        return self.name


class WarnningCode(StrEnum):
    TIP = "W000"
    GLASSES = "W001"
    FACE_MASK = "W002"
    FACE_SPOOFING = "W003"
    LEFT_HANGING = "W004"
    RIGHT_HANGING = "W005"
    FACE_ROTATION = "W006"
    EYE_STATUS = "W007"


error_msgs = {
    ErrorCode.FACE_MINIMUM_WIDTH: string.Template(
        "脸宽小于$face_min_width像素，请检查照片"
    ),
    ErrorCode.FACE_WIDTH_LARGER: "脸部过宽，可能存在照片变形情况，请检查照片",
    ErrorCode.FACE_WIDTH_SMALL: "可能存在照片变形情况，请检查照片",
    ErrorCode.BODY_SMALL: "身子过小，请拍摄/上传半身照片",
    ErrorCode.BODY_LARGER: "可能存在照片变形情况，请检查照片",
    ErrorCode.STANARD_WIDTH_LARGER: "图片宽度过小，请检查照片",
    ErrorCode.STANARD_HEIGHT_LARGER: "图片身子过小，请检查照片",
    ErrorCode.BOTTOM_HANGING: "图片身子过小，请检查照片",
    ErrorCode.LEFT_HANGING: "人像距离照片边缘过小，无法进行标准化，请重新拍摄/上传",
    ErrorCode.RIGHT_HANGING: "人像距离照片边缘过小，无法进行标准化，请重新拍摄/上传",
    ErrorCode.FACE_ROTATION: string.Template(
        "人物头$direction超过$face_ratio_max度，请重新拍摄/上传照片"
    ),
    ErrorCode.FACE_MASK: "不要遮挡面部",
    ErrorCode.FACE_BLUR: "人脸模糊，请检查照片",
    ErrorCode.HEAD_TOP: "头顶距离不够、人像缺失，请检查照片",
}
warning_msgs = {
    WarnningCode.GLASSES: "常戴眼镜者可佩戴眼镜,但不得戴有色(含隐形)眼镜，镜框不得遮挡眼眶、眼球，眼镜不能有反光",
    WarnningCode.FACE_MASK: string.Template("$face_part可能有遮挡或该部分阴影过重"),
    WarnningCode.FACE_SPOOFING: "该照片可能是合成图或者美颜过度",
    WarnningCode.LEFT_HANGING: "人像偏左，没有处于照片中心位置",
    WarnningCode.RIGHT_HANGING: "人像偏右，没有处于照片中心位置",
    WarnningCode.FACE_ROTATION: string.Template("头部向$direction歪头超过$rotation度"),
    WarnningCode.EYE_STATUS: string.Template("$eye_part有可能闭合"),
}

face_part_name = {
    "left_eye": "左眼",
    "right_eye": "右眼",
    "nose": "鼻子",
    "mouth": "嘴巴",
    "left_cheek": "左脸颊",
    "right_cheek": "右脸颊",
    "chin_contour": "下巴",
}


class BottomTransparentShape(BaseModel):
    y1: int
    y2: int
    shape: dict[int, int]


# 图片坐标转直角坐标
def image_point_2_coordinate(point, size):
    mx = size[0] / 2
    mh = size[1] / 2
    x = point[0]
    y = point[1]
    x1 = x - mx
    y1 = mh - y
    return x1, y1


# 直角坐标转图片坐标
def cordinate_2_image_point(point, size):
    mx = size[0] / 2
    mh = size[1] / 2
    x = point[0]
    y = point[1]
    x1 = int(x + mx)
    y1 = int(mh - y)
    if x1 < 0:
        x1 = 0
    elif x1 > size[0]:
        x1 = size[0]
    if y1 < 0:
        y1 = 0
    elif y1 > size[1]:
        y1 = size[1]
    return x1, y1


def point_rotae_point(point, angle):
    cos_angle, sin_angle = math.cos(math.radians(angle)), math.sin(math.radians(angle))
    cos_angle = round(cos_angle, 6)
    sin_angle = round(sin_angle, 6)
    x1 = point[0] * cos_angle - point[1] * sin_angle
    y1 = point[0] * sin_angle + point[1] * cos_angle
    return x1, y1


def fix_rotate_image(image: Image, angle, pivot_point):
    width, height = image.size
    cos_angle, sin_angle = math.cos(math.radians(angle)), math.sin(math.radians(angle))
    cos_angle = round(cos_angle, 6)
    sin_angle = round(sin_angle, 6)
    new_width = int(width * abs(cos_angle) + height * abs(sin_angle))
    new_height = int(height * abs(cos_angle) + width * abs(sin_angle))

    # 创建一个新图片用于绘制旋转后的图片
    rotated_image = Image.new(
        "RGBA", (new_width, new_height), color=(255, 255, 255, 255)
    )
    rgba_image = image.convert("RGBA")

    x = (new_width - width) // 2
    y = (new_height - height) // 2
    rotated_image.paste(rgba_image, (x, y), rgba_image)

    source_a = (x, y)
    source_b = (x + width, y)
    source_c = (x + width, y + height)
    source_d = (x, y + height)

    # 设置旋转中心
    rotated_image = rotated_image.rotate(angle, center=pivot_point)

    a = cordinate_2_image_point(
        point_rotae_point(
            image_point_2_coordinate(source_a, rotated_image.size), angle
        ),
        rotated_image.size,
    )
    b = cordinate_2_image_point(
        point_rotae_point(
            image_point_2_coordinate(source_b, rotated_image.size), angle
        ),
        rotated_image.size,
    )
    c = cordinate_2_image_point(
        point_rotae_point(
            image_point_2_coordinate(source_c, rotated_image.size), angle
        ),
        rotated_image.size,
    )
    d = cordinate_2_image_point(
        point_rotae_point(
            image_point_2_coordinate(source_d, rotated_image.size), angle
        ),
        rotated_image.size,
    )

    optimize_cent = 0.01
    optimize_w = int(rotated_image.width * optimize_cent)
    optimize_h = int(rotated_image.height * optimize_cent)
    # 顶部y
    ty = 0
    if a[1] >= b[1]:
        ty = a[1]
    else:
        ty = b[1]
    lx = 0
    if a[0] >= d[0]:
        lx = a[0]
    else:
        lx = d[0]

    lt_point = (lx + optimize_w, ty + optimize_h)
    # 右边
    rx = 0
    if b[0] <= c[0]:
        rx = b[0]
    else:
        rx = c[0]
    # 底部
    by = 0
    if c[1] <= d[1]:
        by = c[1]
    else:
        by = d[1]

    rb_point = (rx - optimize_w, by - optimize_h)
    # 裁剪图片
    t_w = rb_point[0] - lt_point[0]
    t_h = rb_point[1] - lt_point[1]
    target = Image.new("RGB", (t_w, t_h), color=(255, 255, 255))
    target.paste(rotated_image, (lt_point[0] * -1, lt_point[1] * -1))

    return target


class PhotoStandard:
    options: dict[str, Any] = {}
    config: PhotoStandardConfig = None
    # 原图
    original_source_image: Image
    source_image: Image
    source_width: int
    source_height: int
    left_bts: BottomTransparentShape
    right_bts: BottomTransparentShape
    # 脸长比列
    face_length_ratio: float = 0.53
    # 头顶位置
    top: int = 0
    # 下巴位置
    chin_position: dict = {}
    # 左脸颊位置
    cheek_left: dict = {}
    # 右脸颊位置
    cheek_right: dict = {}
    # 鼻子位置
    nose_tip: dict = {}
    # 中心位置
    center_x: float = 0
    center_y: float = 0

    # 人脸矩形框
    face_location: Rectangle
    # 眼镜
    eye_status: EyeStatus = None
    # 眼镜置信度
    glasses_probability: float = 0
    # 口罩
    mask_probability: float = 0
    # 人脸模糊
    face_blur: float = 0
    # 人脸融合值
    face_spoofing: float = 0
    # 人脸质量
    face_quality: dict[str, float] = None

    # 脸
    face_width: int = 0
    face_height: int = 0
    face_rotation: int = 0

    # 标准化背景图
    bg_image: Image
    bg_image_width: int = 0
    bg_image_height: int = 0

    """
    偏移量 用于中心计算使用，比如图片宽为480，中心点为240
    1、假设鼻子x等200，那么需要先将鼻子移动到中心点范围：231-249（中心点范围为上下浮动），那么偏移量为231-200=31
    2、假设鼻子x扽与300，那么需要先将鼻子移动到中心点范围：231-249（中心点范围为上下浮动）,那么偏移量为：249-300=-51
  """
    offset_x: float = 0
    # 绘制图y轴
    result_y: float = 0
    # 绘制x轴位置
    result_x: int = 0
    # 左半边宽度
    result_left_width: int = 0
    # 右半边宽度
    result_right_width: int = 0
    # 结果
    result: Image

    # 警告信息
    warning: List[PhotoStandardWarning] = None

    def __init__(
        self,
        image_base64: str,
        options=None,
        config: PhotoStandardConfig = PhotoStandardConfig(),
    ):
        if options is None:
            options = {}
        if not image_base64:
            raise Exception("image_base64 cannot be None")

        if self.warning is None:
            self.warning = []
        source_image = base642PIL(image_base64)
        if source_image.mode == "P":
            source_image = source_image.convert("RGB")
        self.source_image = source_image
        self.original_source_image = self.source_image.copy()
        self.face_location = options["face_location"]

        source_width, source_height = self.source_image.size
        self.options = options
        self.config = config

        self.top = options["top"]
        self.source_width = source_width
        self.source_height = source_height
        self.init_face()

        # m = base642PIL(self.get_intermediate_mark_photo())
        # m.save(f"标记图片.jpg")
        # if self.face_rotation != 0:
        #   rate_center = (self.nose_tip["x"], self.nose_tip["y"])
        #   self.get_rotate_info(rate_center)
        self.init_image()

        if config.check:
            code, msg = self.check_basic()
            if code:
                raise BaseException(status_code=code, detail=msg)

        # 旋转处理
        # if self.face_rotation != 0:
        #   rate_center = (self.nose_tip["x"], self.nose_tip["y"])
        #   self.source_image = self.source_image.rotate(self.face_rotation, center=rate_center)

    def get_rotate_info(self, rotete_center: tuple[float, float]):
        rotated_image_rgba = self.source_image.convert("RGBA")
        rotated_image_rgba = rotated_image_rgba.rotate(2, center=rotete_center)
        w, h = rotated_image_rgba.size
        last_y_index = h - 1
        last_x_index = w - 1
        pixels = rotated_image_rgba.load()
        # 1. 左边
        left: dict[int, int] = {}
        x = 0
        y = last_y_index
        pixel = pixels[x, y]
        while pixel == (0, 0, 0, 0) and y >= 0:
            # 向右遍历
            for i in range(w):
                p = pixels[i, y]
                if p != (0, 0, 0, 0):
                    left[y] = i
                    break
            y -= 1
            pixel = pixels[x, y]
        self.left_bts = BottomTransparentShape(y1=y + 1, y2=last_y_index, shape=left)
        # 2. 右边
        right: dict[int, int] = {}
        x = last_x_index
        y = last_y_index
        pixel = pixels[x, y]
        while pixel == (0, 0, 0, 0) and y >= 0:
            # 向右遍历
            for i in range(w):
                xx = last_x_index - i
                p = pixels[xx, y]
                if p != (0, 0, 0, 0):
                    right[y] = i
                    break
            y -= 1
            pixel = pixels[x, y]
        self.right_bts = BottomTransparentShape(y1=y + 1, y2=last_y_index, shape=right)

    # 初始化脸相关
    def init_face(self):
        options = self.options
        self.chin_position = options["chin_position"]
        self.cheek_left = options["cheek_left"]
        self.cheek_right = options["cheek_right"]
        self.nose_tip = options["nose_tip"]
        self.center_y = self.nose_tip.get("y", 0)
        # 严格模式使用鼻子作为位中心点
        if self.config.mode == PhotoStandardMode.STRICT:
            self.offset_x = 0
            self.center_x = self.nose_tip.get("x", 0)
        # 自动优化模式，则做中心点优化处理
        else:
            self.center_x = self.source_width / 2
            nose_x = self.nose_tip.get("x", 0)
            center_range = [
                math.floor(self.center_x - 9),
                math.floor(self.center_x + 9),
            ]
            if nose_x < center_range[0]:
                self.offset_x = center_range[0] - nose_x  # 正数
            elif nose_x > center_range[1]:
                self.offset_x = center_range[1] - nose_x  # 负数
            else:
                self.offset_x = 0

        a2 = abs(self.cheek_left["x"] - self.cheek_right["x"]) ** 2
        b2 = abs(self.cheek_left["y"] - self.cheek_right["y"]) ** 2
        self.face_width = int(math.sqrt(a2 + b2))
        # 脸长
        self.face_height = self.chin_position["y"] - self.top
        self.face_rotation = options.get("rotation", self.face_rotation)
        self.face_length_ratio = self.config.face_length_ratio
        self.eye_status = options.get(
            "eye_status",
            EyeStatus(left_eye=1.0, right_eye=1.0),
        )
        self.glasses_probability = options.get("glasses_probability", 0)
        self.mask_probability = options.get("mask_probability", 0)
        self.face_blur = options.get("face_blur", 0)
        self.face_spoofing = options.get("face_spoofing", 0)
        self.face_quality = options.get(
            "face_quality",
            {
                "left_eye": 0,
                "right_eye": 0,
                "nose": 0,
                "mouth": 0,
                "left_cheek": 0,
                "right_cheek": 0,
                "chin_contour": 0,
            },
        )

    def init_image(self, optimize=False):
        # 1、计算标准化背景图片 w h
        self.bg_compute(self.face_length_ratio, optimize)
        # 2、计算出原图绘制在标准化图片的x，y周 w h
        self.init_image_info()

    def check_basic(self):
        config = self.config

        code: Union[str, StrEnum, None] = None
        msg: Union[str, StrEnum, None] = None

        if not config.check:
            return code, msg

        if self.top == 0:
            code = ErrorCode.HEAD_TOP
            msg = error_msgs[ErrorCode.HEAD_TOP]

        # 脸宽最小值判断
        if self.face_width < config.face_min_width:
            code = ErrorCode.FACE_MINIMUM_WIDTH
            msg = error_msgs[ErrorCode.FACE_MINIMUM_WIDTH].substitute(
                face_min_width=config.face_min_width
            )
        # 左边偏头
        elif self.face_rotation > config.face_ratio_max:
            code = ErrorCode.FACE_ROTATION
            msg = error_msgs[ErrorCode.FACE_ROTATION].substitute(
                direction="左边", face_ratio_max=config.face_ratio_max
            )
        # 右边偏头
        elif self.face_rotation < config.face_ratio_max * -1:
            code = ErrorCode.FACE_ROTATION
            msg = error_msgs[ErrorCode.FACE_ROTATION].substitute(
                direction="右边", face_ratio_max=config.face_ratio_max
            )
        # 眼睛闭合：更精确地提示左眼/右眼/左右眼可能闭合
        elif self.eye_status and (
            self.eye_status.left_eye < config.eye_status
            or self.eye_status.right_eye < config.eye_status
        ):
            low_left = self.eye_status.left_eye < config.eye_status
            low_right = self.eye_status.right_eye < config.eye_status
            if low_left and low_right:
                eye_msg = "左眼和右眼"
            elif low_left:
                eye_msg = "左眼"
            else:
                eye_msg = "右眼"
            self.warning.append(
                PhotoStandardWarning(
                    code=WarnningCode.EYE_STATUS,
                    msg=warning_msgs[WarnningCode.EYE_STATUS].substitute(
                        eye_part=eye_msg
                    ),
                )
            )
        # 眼镜
        elif self.glasses_probability > config.glasses_probability:
            self.warning.append(
                PhotoStandardWarning(
                    code=WarnningCode.GLASSES, msg=warning_msgs[WarnningCode.GLASSES]
                )
            )
        # 口罩
        elif self.mask_probability > config.mask_probability:
            code = ErrorCode.FACE_MASK
            msg = error_msgs[ErrorCode.FACE_MASK]
        # 人脸模糊
        elif self.face_blur > config.face_blur:
            code = ErrorCode.FACE_BLUR
            msg = error_msgs[ErrorCode.FACE_BLUR]
        # 人脸融合
        elif self.face_spoofing > config.face_spoofing:
            self.warning.append(
                PhotoStandardWarning(
                    code=WarnningCode.FACE_SPOOFING,
                    msg=warning_msgs[WarnningCode.FACE_SPOOFING],
                )
            )
        else:
            # 遮挡提示
            w_code: Union[WarnningCode, None] = None
            w_msgs: List[str] = []
            for key, value in self.face_quality.items():
                if value > config.face_quality[key]:
                    w_code = WarnningCode.FACE_MASK
                    w_msgs.append(
                        warning_msgs[WarnningCode.FACE_MASK].substitute(
                            face_part=face_part_name[key]
                        )
                    )
            if w_code:
                self.warning.append(
                    PhotoStandardWarning(code=w_code, msg=",".join(w_msgs))
                )

        return code, msg

    """
  1、要么报错
  2、要么得标准化的图片，然后他的优化步长：0.001
  """

    def bg_compute(self, radio, optimize=False, error_code=None, error_msg=None):
        config = self.config
        self.bg_image_height = int(self.face_height / radio)
        self.bg_image_width = int(config.photo_ratio * self.bg_image_height)

        # bg_middle = self.bg_image_width / 2
        #
        # result_left_width = self.nose_tip["x"]
        # result_right_width = self.source_width - self.nose_tip["x"]
        # bg_top = self.bg_image_height * config.overhead_position
        # result_y = bg_top - self.top
        # 计算脸宽比列，看是否满足条件
        w_ratio = self.face_width / self.bg_image_width

        if round(radio, 8) > config.face_length_ratio_range[1]:
            # 脸长 > 0.64
            if w_ratio < config.face_width_ratio_range[0]:
                # 脸宽 < 0.38
                raise BaseException(
                    status_code=ErrorCode.FACE_WIDTH_SMALL,
                    detail=error_msgs[ErrorCode.FACE_WIDTH_SMALL],
                )
            else:
                raise BaseException(status_code=error_code, detail=error_msg)
        if radio < config.face_length_ratio_range[0]:
            # 脸长 < 0.53
            if w_ratio > config.face_width_ratio_range[1]:
                # 脸宽 > 0.62
                raise BaseException(
                    status_code=ErrorCode.FACE_WIDTH_LARGER,
                    detail=error_msgs[ErrorCode.FACE_WIDTH_LARGER],
                )

        if w_ratio > config.face_width_ratio_range[1]:
            raise BaseException(
                status_code=ErrorCode.BODY_SMALL,
                detail=error_msgs[ErrorCode.BODY_SMALL],
            )
        if w_ratio < config.face_width_ratio_range[0]:
            self.face_length_ratio += config.face_length_ratio_step
            # print("-----------------------")
            # print(f"脸宽不够：{w_ratio} < {config.face_width_ratio_range[0]}")
            # print("-----------------------")
            self.bg_compute(self.face_length_ratio)
        elif w_ratio > config.face_width_ratio_range[1]:
            self.face_length_ratio -= config.face_length_ratio_step
            # print("-----------------------")
            # print(f"脸宽超过：{w_ratio} > {config.face_width_ratio_range[1]}")
            # print("-----------------------")
            self.bg_compute(self.face_length_ratio)
        # 脸宽计算出来后，如果导致宽度大于原图宽度，可以急需优化
        else:
            self.init_image_info()
            error_code, error_msg = self.check_image()
            if error_code and error_msg:
                self.face_length_ratio += config.face_length_ratio_step
                # print("-----------------------")
                # print(f"检查图片不过：{error_code} , {error_msg}")
                # print("-----------------------")
                self.bg_compute(
                    self.face_length_ratio,
                    optimize=True,
                    error_code=error_code,
                    error_msg=error_msg,
                )

    def init_image_info(self):
        config = self.config
        # 1、计算y轴
        bg_top = self.bg_image_height * config.overhead_position
        self.result_y = bg_top - self.top
        # 2、计算x轴
        bg_middle = self.bg_image_width / 2
        self.result_x = int(bg_middle - self.center_x)
        # 3、计算左侧距离
        self.result_left_width = int(self.center_x - self.offset_x) - 1
        # 4、计算右侧距离
        self.result_right_width = self.source_width - self.result_left_width - 1
        # self.printSelfInfo()

    def check_image(self):
        if not self.config.check:
            return None, None
        bg_middle = self.bg_image_width / 2
        code: Union[str, StrEnum, None] = None
        msg: Union[str, StrEnum, None] = None
        # 比较标准后的背景尺寸
        if self.bg_image_width > self.source_width:
            code = ErrorCode.STANARD_WIDTH_LARGER
            msg = error_msgs[ErrorCode.STANARD_WIDTH_LARGER]
        if self.bg_image_height > self.source_height:
            code = ErrorCode.STANARD_HEIGHT_LARGER
            msg = error_msgs[ErrorCode.STANARD_HEIGHT_LARGER]
        # 判断底部是否悬空
        elif self.source_height < self.bg_image_height - self.result_y:
            code = ErrorCode.BOTTOM_HANGING
            msg = error_msgs[ErrorCode.BOTTOM_HANGING]
        # 判断左边是否悬空
        elif self.result_left_width < bg_middle:
            code = ErrorCode.LEFT_HANGING
            msg = error_msgs[ErrorCode.LEFT_HANGING]
        # 判断右边是否悬空
        elif self.result_right_width < bg_middle:
            code = ErrorCode.RIGHT_HANGING
            msg = error_msgs[ErrorCode.RIGHT_HANGING]
        # 修复倾斜角度后的底部判断
        # elif self.face_rotation != 0:
        #   # 底部高度
        #   source_bottom_surplu = self.source_height - (self.bg_image_height - self.result_y)
        #   source_y = math.ceil(self.source_height - source_bottom_surplu)
        #   # 获取切割的部分y轴在x轴上是否有透明度颜色
        #   left_length = self.left_bts.shape.get(source_y, 0)
        #   right_length = self.right_bts.shape.get(source_y, 0)
        #   # 左边判断
        #   if abs(bg_middle - self.result_left_width) < left_length:
        #     code = ErrorCode.LEFT_HANGING
        #     msg = error_msgs[ErrorCode.LEFT_HANGING]
        #   # 右边判断
        #   elif abs(bg_middle - self.result_right_width) < right_length:
        #     code = ErrorCode.RIGHT_HANGING
        #     msg = error_msgs[ErrorCode.RIGHT_HANGING]

        return code, msg

    def check_image_pixels(self, image: Image):
        pixels = image.load()
        bg_color = hex_to_rgb(self.config.background_color)
        for i in range(480):
            color = pixels[i, 639]
            if bg_color == color:
                code = ErrorCode.BOTTOM_HANGING
                msg = error_msgs[ErrorCode.BOTTOM_HANGING]
                raise BaseException(status_code=code, detail=msg)

    # 创建标准照片
    def create_standard_photo(self) -> Image:
        color = ImageColor.getrgb(self.config.background_color)
        # result = Image.new("RGBA", (self.bg_image_width, self.bg_image_height), color)
        result = Image.new("RGB", (self.bg_image_width, self.bg_image_height), color)
        # rgba用下面这个去添加
        # result.paste(self.source_image, (int(self.result_x), int(self.result_y)), self.source_image)
        # rgb用下面这个去添加
        x = int(self.result_x + self.offset_x)
        y = int(self.result_y)
        result.paste(self.source_image, (x, y))
        # small = result.resize((480, 640), resample=Image.Resampling.NEAREST)
        # result.save("image_result.jpg", dpi=(300, 300), quality=100)
        # small.save("image_small.jpg", dpi=(300, 300), quality=100)
        # result = result.convert("RGB")
        # result.save("image_result-480x640.jpg", dpi=self.config.dpi)
        # if self.config.check:
        #   self.check_image_pixels(result.resize((480, 640)))
        return result

    def get_standard_photo(
        self,
    ) -> Tuple[Image.Image, Union[None, PhotoStandardWarning]]:
        error_code, error_msg = self.check_image()
        if error_code and self.config.mode == PhotoStandardMode.STRICT:
            raise BaseException(status_code=error_code, detail=error_msg)
        elif not error_msg:
            # 如果检查没有问题，并且是严格模式
            result = self.create_standard_photo()
            self.result = result
            return result, self.warning

        # 检查有问题，并且是自动优化模式
        while self.face_length_ratio < 1 and error_code:
            # 累加去减小标准化背景，以达到去除悬空的目的
            self.face_length_ratio += self.config.face_length_ratio_step
            self.init_image(True)
            error_code, error_msg = self.check_image()
        if error_msg:
            raise BaseException(status_code=error_code, detail=error_msg)
        result = self.create_standard_photo()
        self.result = result
        return result, self.warning

    def resize(self, image: Image, size: List[int] = None) -> Image:
        if size is None or len(size) != 2:
            size = self.config.compression_size
        return image.resize(tuple(size))

    def get_intermediate_mark_photo(self):
        line_color = (255, 0, 0)
        rect_color = (240, 0, 0)
        line_width = 2

        font_file_path = os.path.join(resource_dir, "simhei.ttf")
        font = ImageFont.truetype(font_file_path, 20)  # 指定字体和大小
        font_color = (255, 69, 0)
        tmp_img = self.original_source_image.convert("RGB")
        draw = ImageDraw.Draw(tmp_img)

        hor_center = self.source_width / 2  # 横向中线
        # ver_center = self.source_height / 2  # 竖向中线

        # 开始画线
        draw.line(
            [(hor_center - 50, self.top), (hor_center + 50, self.top)],
            fill=line_color,
            width=line_width,
        )  # 头顶位置
        draw.text(
            (hor_center - 50, self.top + 10),
            f"head{self.top}",
            fill=font_color,
            font=font,
        )
        # 下巴位置
        draw.line(
            [
                (hor_center - 50, self.chin_position["y"]),
                (hor_center + 50, self.chin_position["y"]),
            ],
            fill=line_color,
            width=line_width,
        )  # 头顶位置
        chin_position_y = self.chin_position["y"]
        draw.text(
            (hor_center - 50, self.chin_position["y"] + 10),
            f"chin{chin_position_y}",
            fill=font_color,
            font=font,
        )
        # 左脸颊位置
        draw.line(
            [
                (self.cheek_left["x"], 100),
                (self.cheek_left["x"], self.source_height - 100),
            ],
            fill=line_color,
            width=line_width,
        )  # 头顶位置
        cheek_left_x = self.cheek_left["x"]
        draw.text(
            (self.cheek_left["x"] + 10, 100),
            f"left{cheek_left_x}",
            fill=font_color,
            font=font,
        )
        # 右脸颊位置
        draw.line(
            [
                (self.cheek_right["x"], 100),
                (self.cheek_right["x"], self.source_height - 100),
            ],
            fill=line_color,
            width=line_width,
        )  # 头顶位置
        cheek_right_x = self.cheek_right["x"]
        draw.text(
            (self.cheek_right["x"] - 10, 100),
            f"right{cheek_right_x}",
            fill=font_color,
            font=font,
        )

        # 人脸框
        draw.line(
            [
                (self.face_location.left, self.face_location.top),
                (
                    self.face_location.left + self.face_location.width,
                    self.face_location.top,
                ),
            ],
            fill=rect_color,
            width=line_width,
        )
        draw.line(
            [
                (
                    self.face_location.left,
                    self.face_location.top + self.face_location.height,
                ),
                (
                    self.face_location.left + self.face_location.width,
                    self.face_location.top + self.face_location.height,
                ),
            ],
            fill=rect_color,
            width=line_width,
        )
        draw.line(
            [
                (self.face_location.left, self.face_location.top),
                (
                    self.face_location.left,
                    self.face_location.top + self.face_location.height,
                ),
            ],
            fill=rect_color,
            width=line_width,
        )
        draw.line(
            [
                (
                    self.face_location.left + self.face_location.width,
                    self.face_location.top,
                ),
                (
                    self.face_location.left + self.face_location.width,
                    self.face_location.top + self.face_location.height,
                ),
            ],
            fill=rect_color,
            width=line_width,
        )

        draw.text(
            (self.face_location.left + 20, self.face_location.top + 20),
            f"脸宽：{self.face_location.width}，脸长：{self.face_location.height}",
            fill=font_color,
            font=font,
        )

        # 开始标点
        # 鼻子位置
        draw.ellipse(
            [
                self.nose_tip["x"] - line_width,
                self.nose_tip["y"] - line_width,
                self.nose_tip["x"] + line_width,
                self.nose_tip["y"] + line_width,
            ],
            fill=line_color,
            outline=None,
        )
        nose_tip_x = self.nose_tip["x"]
        nose_tip_y = self.nose_tip["y"]
        draw.text(
            (self.nose_tip["x"] - 20, self.nose_tip["y"] - 30),
            f"nose{nose_tip_x, nose_tip_y}",
            fill=font_color,
            font=font,
        )

        draw.text(
            (self.nose_tip["x"], self.nose_tip["y"] + 30),
            f"rotation{self.face_rotation}",
            fill=font_color,
            font=font,
        )

        return PIL2base64(tmp_img)

    def printSelfInfo(self):
        print("-------------------------------------------------------------")
        print("当前使用脸长比例", self.face_length_ratio)
        print("原图高宽:", self.source_width, self.source_height)
        print("标准化图片:", self.bg_image_width, self.bg_image_height)
        print("绘制坐标:", self.result_x, self.result_y)
        print("脸宽:", self.face_width)
        print("脸宽比例", self.face_width / self.bg_image_width)
        print("脸长:", self.face_height)
        print("脸长比例", self.config.face_length_ratio)
        print("旋转", self.face_rotation)
        print("头顶和下吧", self.top, self.chin_position)
        print("鼻子位置", self.nose_tip)
        print("中心位置", self.center_x)
        print("偏移位置", self.offset_x)
